package com.tvunetworks.center.user.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tvunetworks.center.common.constant.LocalConstant;
import com.tvunetworks.center.common.exception.RpcException;
import com.tvunetworks.center.common.exception.ServerException;
import com.tvunetworks.center.common.model.LoginUser;
import com.tvunetworks.center.common.model.param.AddAndRemoveUserServiceParam;
import com.tvunetworks.center.common.model.param.RegisterUserParam;
import com.tvunetworks.center.common.model.param.UpdateUserEmailParam;
import com.tvunetworks.center.common.model.vo.UserInfoVo;
import com.tvunetworks.center.common.util.JsonUtil;
import com.tvunetworks.center.common.util.MyUtil;
import com.tvunetworks.center.common.util.Result;
import com.tvunetworks.center.common.util.ResultUtil;
import com.tvunetworks.center.user.mapper.UserDeleteRecordMapper;
import com.tvunetworks.center.user.mapper.UserDeviceMapper;
import com.tvunetworks.center.user.mapper.UserMapper;
import com.tvunetworks.center.user.model.User;
import com.tvunetworks.center.user.model.UserDeleteRecord;
import com.tvunetworks.center.user.model.json.ExcelData;
import com.tvunetworks.center.user.model.param.*;
import com.tvunetworks.center.user.model.result.ResultConstant;
import com.tvunetworks.center.user.model.vo.*;
import com.tvunetworks.center.user.service.*;
import com.tvunetworks.center.user.service.feign.MessageRecordFeignService;
import com.tvunetworks.center.user.service.feign.TokenFeignService;
import com.tvunetworks.center.user.service.feign.UserGroupFeignService;
import com.tvunetworks.center.user.util.AccessServerUtil;
import com.tvunetworks.center.user.util.RedisUtil;
import com.tvunetworks.center.user.util.UserThreadPool;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.*;

/**
 * @program: tvucc-user
 * @description: UserServiceImpl
 * @author lebronchen
 * @create: 2019-02-28 16:53
 **/
@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private UserHttpService userHttpService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserDeviceService userDeviceService;
    @Autowired
    private UserDeviceMapper userDeviceMapper;
    @Autowired
    private BookmarkDeviceService bookmarkDeviceService;
    @Autowired
    private UserFeatureService userFeatureService;
    @Autowired
    private UserGroupFeignService userGroupFeignService;
    @Autowired
    private AccessServerUtil accessServerUtil;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private MessageRecordFeignService messageRecordFeignService;
    @Autowired
    private UserDeleteRecordMapper userdeleteRecordMapper;
    @Autowired
    private UserDeleteRecordService userDeleteRecordService;
    @Autowired
    private TokenFeignService tokenFeignService;
    @Autowired
    private UserBookmarkService userBookmarkService;
    @Autowired
    private RoleManagementService roleManagementService;
    @Autowired
    private RoleUserService roleUserService;



    @Value("${session.valid.time}")
    private Long sessionValidTime;
    @Value("${settingTab.superAdmin}")
    private String superAdminSettingTab;
    @Value("${settingTab.support}")
    private String supportSettingTab;
    @Value("${settingTab.admin}")
    private String adminSettingTab;
    @Value("${settingTab.user}")
    private String userSettingTab;
    @Value("${serviceNameInAuthorizationService}")
    private String serviceNameInAuthorizationService;
    @Value("${gridmarketTest.url}")
    private String gridMarketUrl;
    @Value("${gridCC.url.getGridNotificationNum}")
    private String getGridNotificationNum;
    @Value("${useUserGroupToCreateUser}")
    private boolean useUserGroupToCreateUser;
    @Value("${enableGridCC}")
    private boolean enableGridCC;
    @Value("${customized.setting.group}")
    private String customizedSettingGroup;
    @Value("${enableCustomizedCC}")
    private boolean enableCustomizedCC;

    @Override
    public Result<LoginUser> getLoginUserAndCheckAuth(String token, String serverName) throws IOException {
        // 1.验证session是否有效
        Result<LoginUser> loginUserResult = userHttpService.userserviceGetUserInfo(token);
        if (!loginUserResult.assertSuccess()) {
            // session失效，直接返回
            return loginUserResult;
        }

        // 2.验证session是否有访问当前服务的权限
        Result<Boolean> authResult = userHttpService.userserviceCheckServiceAccessable(token, serverName);
        if (!loginUserResult.assertSuccess()) {
            return ResultUtil.error(authResult.getErrorCode(), authResult.getErrorInfo());
        }
        if (!authResult.getResult()) {
            return ResultUtil.error("103", "No authority");
        }
        LoginUser loginUser = loginUserResult.getResult();

        supplementAndSetLoginUser(loginUser, token);

        return loginUserResult;
    }

    @Override
    public Result<LoginUser> getLoginUser(String token) throws IOException {
        // 1.验证session是否有效
        Result<LoginUser> loginUserResult = userHttpService.userserviceGetUserInfo(token);
        if (!loginUserResult.assertSuccess()) {
            // session失效，直接返回
            return loginUserResult;
        }

        // 2.验证session是否有访问当前服务的权限
        Result<Boolean> authResult = userHttpService.userserviceCheckServiceAccessable(token);
        if (!loginUserResult.assertSuccess()) {
            return ResultUtil.error(authResult.getErrorCode(), authResult.getErrorInfo());
        }
        if (!authResult.getResult()) {
            return ResultUtil.error("103", "No authority");
        }

        // 3.返回当前登陆用户
        // session可用
        LoginUser loginUser = loginUserResult.getResult();
        supplementAndSetLoginUser(loginUser, token);
        return loginUserResult;
    }

    @Override
    public synchronized Result<LoginUser>  getLoginUserWithNoCheck(String token) throws IOException {
        // 1.验证session是否有效
        Result<LoginUser> loginUserResult = userHttpService.userserviceGetUserInfo(token);
        if (loginUserResult.assertSuccess()) {
            LoginUser loginUser = loginUserResult.getResult();
            supplementAndSetLoginUser(loginUser, token);
        }
        return loginUserResult;
    }

    @Override
    public Result<com.tvunetworks.center.common.model.User> getUserWithNoCheck(String token) throws IOException {
        // 1.验证session是否有效
        Result<LoginUser> loginUserResult = userHttpService.userserviceGetUserInfo(token);
        if (loginUserResult.assertSuccess()) {
            LoginUser loginUser = loginUserResult.getResult();
            User user = supplementAndSetLoginUser(loginUser, token);
            if(user != null){
                com.tvunetworks.center.common.model.User fullUserInfo = JsonUtil.convertValue(user, com.tvunetworks.center.common.model.User.class);
                return ResultUtil.success(fullUserInfo);
            } else {
                log.error("getUserWithNoCheck error, LoginUser info email:",loginUser.getEmail());
            }
        }

        return ResultUtil.error(loginUserResult.getErrorCode(),loginUserResult.getErrorInfo());
    }

    @Override
    public Result<LoginUser> getLoginUserWithCheck(String token) throws IOException {
        // 获取登陆用户
        Result<LoginUser> loginUserResult = this.getLoginUser(token);
        if (loginUserResult.assertSuccess()) {
            // 如果用户登陆成功，判断用户是否在DB存在，不存在则创建
            LoginUser loginUser = loginUserResult.getResult();
            User dbUser = this.getByEmail(loginUser.getEmail());
            if (dbUser == null) {
                this.createUser(loginUser);
            }
        }

        return loginUserResult;
    }

    private void createUser(LoginUser loginUser){
        User user = new User()
                .setId(loginUser.getId())
                .setEmail(loginUser.getEmail())
                .setRole(LocalConstant.UserRole.USER)
                .setActive("1");
        userMapper.insert(user);
    }

    @Override
    public Result<Void> logout(String token) throws IOException {
        return userHttpService.userserviceLogout(token);
    }

    @Override
    public Result<String> getUserRole(String email, String token) {
        return userHttpService.getUserRole(email, token);
    }

    @Override
    @Transactional
    public void add(User user) {
        userMapper.insert(user);
    }

    @Override
    public List<User> selectAll() {
        return userMapper.selectAll();
    }

    /**
     *
     * @param param      查询参数封装在user对象中
     * @param pageNum   pageNum默认值1
     * @param pageSize  pageSize默认值10
     * @return
     */
    @Override
    public PageInfo<PageUserVo> pageUser(LoginUser loginUser, SearchUserParam param, int pageNum, int pageSize) {
        // 分页插件开启分页
        PageHelper.startPage(pageNum, pageSize);

        String email = param.getEmail();
        email = MyUtil.formatCondition(email);

        // 根据searchUserRole判断查询用户是support还是admin
        String searchUserRole = loginUser.getRole();
        List<PageUserVo> users;
        if (StringUtils.equals(searchUserRole, LocalConstant.UserRole.ADMIN)) {
            // admin查询自己创建的用户
            users = userMapper.adminListUser(loginUser.getId(), email);
        } else {
            // support查询指定role的用户
            if (StringUtils.isBlank(param.getAccountType())) {
                // support查询必须指定role
                return new PageInfo<>();
            }
            users = userMapper.supportListUser(param.getAccountType(), email, param.getAgreement());
        }

        if (!param.isNotNeedCount()) {
            // 查询 R和Source数量
            if (users != null && users.size() > 0) {
                for (PageUserVo user : users) {
                    int receiverCount = userDeviceMapper.countReceiver(user.getId());
                    int sourceCount = userDeviceMapper.countSource(user.getId());
                    List<String> tokenAnywhereIds = userDeviceService.getTokenAnywhereIds(user.getId(), null, Boolean.FALSE, null, Boolean.TRUE);
                    if (!CollectionUtils.isEmpty(tokenAnywhereIds)) {
                        sourceCount += tokenAnywhereIds.size();
                    }
                    user.setReceiverCount(receiverCount);
                    user.setSourceCount(sourceCount);
                }
            }
        }


        // 查询 User 账号时显示其父亲账号 email
        if (!StringUtils.equals(searchUserRole, LocalConstant.UserRole.ADMIN) && StringUtils.equals(param.getAccountType(), LocalConstant.UserRole.USER)) {
            for (PageUserVo user : users) {
                String userParentId = user.getUserParentId();
                if (StringUtils.isNotEmpty(userParentId)) {
                    User parent = this.getById(userParentId);
                    if (parent != null) {
                        user.setUserParentEmail(parent.getEmail());
                    }
                }

            }
        }

        return new PageInfo<>(users);
    }

    @Override
    public User getByEmail(String email) {
        User record = new User();
        record.setEmail(email);
        List<User> list = userMapper.select(record);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return list.get(0);
    }

    @Override
    public User getById(String id) {
        return userMapper.getById(id);
    }

    @Override
    public List<User> listUser() {

        PageHelper.startPage(2, 10, true);

        return userMapper.selectAll();
    }

    @Override
    @Transactional
    public int setRole(String userId, String role,LoginUser loginUser) {
        User user = this.getById(userId);
        if (user == null) {
            // user 不存在
            return 1;
        }
        if (StringUtils.equals(user.getRole(), role)) {
            // 用户已经是当前role
            return 2;
        }
        if (StringUtils.equals(LocalConstant.UserRole.USER, role)) {
            // admin - user
            List<String> sonIds = userMapper.listSonUserIds(userId);
            if (sonIds != null && sonIds.size() > 0) {
                // 1.清除孩子账号的 parentId
                userMapper.removeSonUserParentId(userId);
            } else {
                sonIds = new ArrayList<>();
            }
            // 移除UserDevice和BookmarkDevice要包括Admin自身
            sonIds.add(userId);

            // 2.清除自己和孩子账号的 UserDevice
            userDeviceMapper.removeUserDevice(sonIds);
            //还需要清除token扫码配对来的设备,自己和孩子账号下都清除
            userDeviceMapper.removeTokenDeviceByUserId(sonIds);
            // 3.清除自己和孩子账号的 BookmarkDevice
            bookmarkDeviceService.removeUserBookmarkDevice(sonIds);
            //4.删除该用户下的所有Role和相关信息
            roleManagementService.deleteByUserId(userId);
        }
        //如果是给support账号降级成Admin,那么support账号下全部的Admin账号的parentId需要清除,
        // 因为Admin的父账号不能还是Admin
        //防止恶意攻击,所以此步骤需要校验当前登录账号是不是super_admin账号
        if (StringUtils.equals(user.getRole(),LocalConstant.UserRole.SUPPORT)
            && StringUtils.equals(LocalConstant.UserRole.ADMIN,role)
            && StringUtils.equals(loginUser.getRole(),LocalConstant.UserRole.SUPER_ADMIN)
        ) {
                //查询出这个support账号下原先的Admin账号
            List<User> adminList = userMapper.getAdminBySupport(userId);
            for (User admin : adminList) {
                admin.setUserParentId(null);
                userMapper.updateByPrimaryKey(admin);
            }
        }
        user.setRole(role);
        // 修改用户级别的时候 都需要把 UserParentId 清空
        user.setUserParentId(null);
        userMapper.updateByPrimaryKey(user);
        roleUserService.deleteByUserId(userId);
        return 0;
    }

    @Override
    @Transactional
    public int setActive(String userId, String active) {
        User user = this.getById(userId);
        if (user == null) {
            // 用户不存在
            return 1;
        }
        if (StringUtils.equals(user.getActive(), active)) {
            // 用户已经是当前状态
            return 2;
        }
        try {
            Result<String> setActiveResult = userHttpService.activateAndDisActivateUser(userId, active);
            if (!setActiveResult.assertSuccess()) {
                // userservice 设置用户是否可用失败
                return 3;
            }
            user.setActive(active);
            userMapper.updateByPrimaryKey(user);
            return 0;
        } catch (RpcException e) {
            log.error(e.toString(), e);
            // 调用userservice接口失败
            return 4;
        }
    }

    @Override
    @Transactional
    public Result<String> createUser(LoginUser loginUser, CreateUserParam createUserParam) {
        String session = createUserParam.getSession();
        String email = createUserParam.getEmail();

        CheckUserVo checkUserVo = this.checkUser(loginUser, session, email);
        if (checkUserVo.isCcExist()) {
            // 用户在 tvucc 已存在
            return ResultUtil.error("81000601", "User already exist in Command Center");
        }
        if (checkUserVo.isAdminCreateExistedUser() && !StringUtils.equals(LocalConstant.UserRole.USER, createUserParam.getAccountType())) {
            // 用户在 tvucc 已存在
            return ResultUtil.error("81000601", "User already exist in Command Center");
        }

        if (!checkUserVo.isUserserviceExist() && StringUtils.isBlank(createUserParam.getPassword())) {
            return ResultUtil.error("8100140508", "Password can not be null");
        }

        String loginUserRole = loginUser.getRole();
        boolean supportCreateUser = StringUtils.equals(loginUserRole, LocalConstant.UserRole.SUPPORT) && StringUtils.equals(LocalConstant.UserRole.USER, createUserParam.getAccountType());
        if (supportCreateUser) {
            // support 创建用户
            // 如果 support 创建user 那么检测ownerId是否存在
            String ownerId = createUserParam.getOwnerId();
            if (StringUtils.isBlank(ownerId)) {
                return ResultUtil.paramError();
            }
            User owner = this.getById(ownerId);
            if (owner == null) {
                return ResultUtil.error("81000603", "Owner not exist");
            }
            if (!StringUtils.equals(LocalConstant.UserRole.ADMIN, owner.getRole())) {
                return ResultUtil.error("81000604", "Owner not admin");
            }

        } else {
            // admin 创建用户
        }

        if (!checkUserVo.isUserserviceExist()) {
            if (useUserGroupToCreateUser) {
                // 调用 UserGroup 接口创建用户
                RegisterUserParam registerUserParam = new RegisterUserParam()
                        .setEmail(createUserParam.getEmail())
                        .setPassword(createUserParam.getPassword())
                        .setStatus(Integer.valueOf(createUserParam.getActive()))
                        .setServiceNames(serviceNameInAuthorizationService)
                        .setFirstName(createUserParam.getFirstName())
                        .setLastName(createUserParam.getLastName());
                String origin = serviceNameInAuthorizationService;
                if (StringUtils.equals(loginUserRole, LocalConstant.UserRole.SUPER_ADMIN)) {
                    origin += " - SuperAdmin - ";
                } else if (StringUtils.equals(loginUserRole, LocalConstant.UserRole.SUPPORT)) {
                    origin += " - Support - ";
                } else {
                    origin += " - Admin - ";
                }
                origin += loginUser.getEmail();
                registerUserParam.setOrigin(origin);
                Result<String> createUserResult = userGroupFeignService.registerUser(registerUserParam);

                if (!createUserResult.assertSuccess()) {
                    return ResultUtil.error("81000605", "Userservice create user failed", createUserResult.getResult());
                }
            }  else {
                // 使用 UserService 创建用户时，FirstName 和 LastName 不会保存，因为 UserService 不接受这两个参数
                Result<String> createUserResult = userHttpService.userServiceCreateUser(createUserParam);
                if (!createUserResult.assertSuccess()) {
                    return ResultUtil.error("81000605", "Userservice create user failed", createUserResult.getResult());
                }
            }

        } else {
            // UserService 已存在，所以不需要重新创建用户，但是如果 active = 1 需要下发 CC 权限
            if (StringUtils.equalsIgnoreCase("1", createUserParam.getActive())) {
                AddAndRemoveUserServiceParam param = new AddAndRemoveUserServiceParam()
                        .setUserId(checkUserVo.getUserId())
                        .setAddServiceNames(serviceNameInAuthorizationService);
                userGroupFeignService.addAndRemoveService(param);
            }
        }

        // 去Userservice检查创建的用户是否存在
        Result<String> getUserIdResult = userHttpService.getUserId(session, email);

        if (!getUserIdResult.assertSuccess()) {
            // 在创建完User之后 Userservice还是查不到
            return ResultUtil.error("81000606", "User not found after create");
        }
        String userId = getUserIdResult.getResult();
        boolean adminCreateExistedUser = checkUserVo.isAdminCreateExistedUser();
        if (adminCreateExistedUser) {
            // CC 为 Admin 创建已存在的 User 用户

            // 只需要设置 UserParentId
            User user = this.getByEmail(email);
            if (supportCreateUser) {
                user.setUserParentId(createUserParam.getOwnerId());
            } else {
                user.setUserParentId(loginUser.getId());
            }
            userMapper.updateByPrimaryKey(user);
        } else {
            // tvucc DB 创建User
            User user = new User();
            BeanUtils.copyProperties(createUserParam, user);
            user.setId(userId);
            user.setRole(createUserParam.getAccountType());
            if (supportCreateUser) {
                user.setUserParentId(createUserParam.getOwnerId());
            } else {
                user.setUserParentId(loginUser.getId());
            }
            user.setCreateUserId(loginUser.getId());
            userMapper.insert(user);
        }

        // 设置feature
        if (StringUtils.equals(loginUserRole, LocalConstant.UserRole.ADMIN) && StringUtils.isNotEmpty(createUserParam.getRoleId())) {
            RoleVo roleVo = roleManagementService.getRoleByRoleId(createUserParam.getRoleId(), loginUser.getId());
            if (roleVo == null) {
                return ResultUtil.error("81000607", "role not exist or role dose not belong of account");
            }
            roleUserService.addRoleUser(roleVo.getRoleId(), userId);
            if (!CollectionUtils.isEmpty(roleVo.getFeatureIds())) {
                AddOrRemoveUserFeatureParam addOrRemoveUserFeatureParam = new AddOrRemoveUserFeatureParam()
                        .setUserId(userId)
                        .setEnableFeatureIds(String.join(",", roleVo.getFeatureIds()));
                userFeatureService.addOrRemoveFeature(addOrRemoveUserFeatureParam);
            }
            if (!CollectionUtils.isEmpty(roleVo.getPeerIds())) {
                userDeviceService.addUserDevice(userId, String.join(",", roleVo.getPeerIds()));
            }
        } else {
            AddOrRemoveUserFeatureParam addOrRemoveUserFeatureParam = new AddOrRemoveUserFeatureParam()
                    .setUserId(userId)
                    .setEnableFeatureIds(createUserParam.getEnableFeatureIds());
            userFeatureService.addOrRemoveFeature(addOrRemoveUserFeatureParam);
        }
        return ResultUtil.success();
    }

    @Override
    public LoginUser getLoginUserByEmail(String email) {
        User user = this.getByEmail(email);
        if (user == null) {
            return null;
        }
        LoginUser loginUser = new LoginUser();
        BeanUtils.copyProperties(user, loginUser);
        return loginUser;
    }

    @Override
    public String getSettingTab(String role) {
        if (StringUtils.equals(LocalConstant.UserRole.SUPER_ADMIN, role)) {
            return superAdminSettingTab;
        } else if (StringUtils.equals(LocalConstant.UserRole.SUPPORT, role)) {
            return supportSettingTab;
        } else if (StringUtils.equals(LocalConstant.UserRole.ADMIN, role)) {
            if (enableCustomizedCC) {
                return adminSettingTab;
            } else {
                List<String> list = Arrays.asList(adminSettingTab.split(","));
                List<String> copyList = new ArrayList<>(list);
                copyList.remove(customizedSettingGroup);
                return String.join(",", copyList);
            }
        } else if (StringUtils.equals(LocalConstant.UserRole.USER, role)) {
            if (enableCustomizedCC) {
                return userSettingTab;
            } else {
                List<String> list = Arrays.asList(userSettingTab.split(","));
                List<String> copyList = new ArrayList<>(list);
                 copyList.remove(customizedSettingGroup);
                return String.join(",", copyList);
            }
        }
        log.error("GetSettingTab role error role:[{}]", role);
        return null;
    }

    @Override
    public List<String> listUserIdByRole(String role) {
        return userMapper.listUserIdByRole(role);
    }

    @Override
    public List<String> listSonUserIds(String userId) {
        return userMapper.listSonUserIds(userId);
    }


    @Override
    public Result<LoginUser> globalGetLoginUser(String token, boolean userServiceRole, String serviceName, boolean checkTvuccDB) throws IOException {
        // 1.验证session是否有效
        Result<LoginUser> loginUserResult = userHttpService.userserviceGetUserInfo(token);
        String code = loginUserResult.getErrorCode();
        if (StringUtils.equalsIgnoreCase("101", code)) {
            return ResultUtil.error("8100140501", "GetUserInfo failed");
        } else if (StringUtils.equalsIgnoreCase("102", code)) {
            return ResultUtil.error("8100140502", "GetUserInfo session invalid");
        }

        LoginUser loginUser = loginUserResult.getResult();

        // 2.设置UserService的role
        if (userServiceRole) {
            Result<String> userRoleResult = userHttpService.getUserRole(loginUser.getEmail(), token);
            code = userRoleResult.getErrorCode();
            if (StringUtils.equalsIgnoreCase("101", code)) {
                return ResultUtil.error("8100140503", "GetUserRole failed");
            } else if (StringUtils.equalsIgnoreCase("102", code)) {
                return ResultUtil.error("8100140504", "GetUserInfo session invalid");
            }
            loginUser.setRole(userRoleResult.getResult());
        }

        // 3.验证session是否有访问当前服务的权限
        if (checkTvuccDB) {
            serviceName = serviceNameInAuthorizationService;
        }
        if (StringUtils.isNotBlank(serviceName)) {
            Result<Boolean> authResult = userHttpService.userserviceCheckServiceAccessable(token, serviceName);
            code = authResult.getErrorCode();
            if (StringUtils.equalsIgnoreCase("101", code)) {
                return ResultUtil.error("8100140505", "ListAccessableService failed");
            } else if (StringUtils.equalsIgnoreCase("102", code)) {
                return ResultUtil.error("8100140506", "ListAccessableService session invalid");
            }
            if (!authResult.getResult()) {
                return ResultUtil.error("8100140507", "No service authority");
            }
        }

        if (!checkTvuccDB) {
            return loginUserResult;
        }

        // 4.返回当前登陆用户
        // session可用
        User user = this.getByEmail(loginUser.getEmail());
        if (user != null) {
            // 将用户基本信息封装到LoginUser中去
            loginUser.setRole(user.getRole());
            loginUser.setActive(user.getActive());
            loginUser.setPhone(user.getPhone());
            loginUser.setCreateUserId(user.getCreateUserId());
            loginUser.setUserParentId(user.getUserParentId());
        } else {
            loginUser.setRole("4");
            loginUser.setActive("1");
            // 登陆用户数据库中不存在，添加到数据库中
            user = new User();
            user.setId(loginUser.getId());
            user.setEmail(loginUser.getEmail());
            user.setRole("4");
            user.setActive("1");
            userMapper.insert(user);
        }
        return loginUserResult;
    }

    @Override
    public CheckUserVo checkUser(LoginUser loginUser, String session, String email) {
        CheckUserVo vo = new CheckUserVo();
        // check 用户在tvucc是否存在
        User ccUser = this.getByEmail(email);
        if (ccUser == null) {
            vo.setCcExist(false);
        } else {
            // Admin在创建一个User，这个User在CC里面，但是没有父亲，那么可以通过
            if ( (LocalConstant.UserRole.SUPPORT.equals(loginUser.getRole()) || LocalConstant.UserRole.ADMIN.equals(loginUser.getRole()))
                    && StringUtils.isBlank(ccUser.getUserParentId()) && LocalConstant.UserRole.USER.equals(ccUser.getRole())) {
                vo.setCcExist(false);
                vo.setAdminCreateExistedUser(true);
            } else {
                vo.setCcExist(true);
            }
        }
        // check 用户在userservice是否存在
        Result<String> userserviceUserResult = userHttpService.getUserId(session, email);
        boolean userserviceUserExist = userserviceUserResult.assertSuccess();
        if (userserviceUserExist) {
            vo.setUserId(userserviceUserResult.getResult());
        }
        vo.setUserserviceExist(userserviceUserExist);
        return vo;
    }

    private static final String SUPER_ADMIN = "Command Center - Super Admin - ";
    private static final String SUPPORT = "Command Center - Support - ";
    private static final String ADMIN = "Command Center - Admin - ";
    private static final String USER = "Command Center - Support(Manual) - ";

    @Override
    public Result<Object> initOriginParam() {
//        List<InitOriginVo> users = userMapper.initOriginParam();
        List<InitOriginVo> users = userMapper.initReleaseOriginParam();
        if (CollectionUtils.isEmpty(users)) {
            return ResultUtil.error("101", "Users is empty");
        }
        Map<String, String> map = new HashMap<>();
        for (InitOriginVo user : users) {
            String origin = null;
            String role = user.getRole();
            String email = user.getEmail();
            String userId = user.getUserId();
            if (StringUtils.isBlank(role) || StringUtils.isBlank(email) || StringUtils.isBlank(userId)) {
                log.error("User abnormal user:[{}]", user);
                continue;
            }
            switch (role) {
                case "1":
                    origin = SUPER_ADMIN;
                    break;
                case "2":
                    origin = SUPPORT;
                    break;
                case "3":
                    origin = ADMIN;
                    break;
                case "4":
                    origin = USER;
                    break;
                default:
                    log.error("User role abnormal user:[{}]", user);
                    continue;
            }
            origin += email;
            map.put(userId, origin);
        }
        return ResultUtil.success(map);
    }

    @Override
    public int countGridNotifyNum(String userId) {
        if (!enableGridCC) {
            return 0;
        }

        try {
            String url = getGridNotificationNum;
            if (!StringUtils.startsWith(url, "http")) {
                url = "http://" + url;
            }
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.add(LocalConstant.API_HEADER_PARAM_KEY, accessServerUtil.generatorAccess());


            Map<String, String> param = new HashMap<>();
            param.put("userId", userId);
            HttpEntity httpEntity = new HttpEntity(JsonUtil.toJsonStr(param), headers);

            ResponseEntity<String> responseEntity;
            log.info("RPC GridMarket NotifyNum url:{} pram:[{}]", url, param);
            try {
                responseEntity = restTemplate.postForEntity(url, httpEntity, String.class);
            } catch (RestClientException e) {
                log.error(e.toString(), e);
                log.error("RPC GridMarket NotifyNum Http error url:{} pram:[{}]", url, param);
                return 0;
            }

            if (responseEntity.getStatusCode() != HttpStatus.OK) {
                log.info("RPC GridMarket NotifyNum HttpStatus not 200 url:{} pram:[{}] responseEntity:[{}]", url, param, responseEntity);
                return 0;
            }
            String result = responseEntity.getBody();
            log.info("RPC GridMarket NotifyNum HttpStatus result url:{} pram:[{}] result:[{}]", url, param, result);

            JsonNode jsonNode = MyUtil.MAPPER.readTree(result);
            if (!(jsonNode.has("errorCode") && "0x0".equalsIgnoreCase(jsonNode.get("errorCode").asText()))) {
                log.info("RPC GridMarket NotifyNum HttpStatus result not success url:{} pram:[{}] result:[{}]", url, param, result);
                return 0;
            }
            int num = jsonNode.get("content").get("num").asInt();
            return num;
        } catch (Exception e) {
            log.error(e.toString(), e);
        }
        return 0;
    }

    @Override
    public int moveUserToOtherAdmin(MoveUserToOtherAdminParam param) {
        //当前选中的账号
        String userId = param.getTargetUserId();
        //新的管理员账号
        String adminUserId = param.getToUserId();
        User user = this.getById(userId);
        if (user == null) {
            // user 不存在
            return  1;
        }
        if (!StringUtils.equals(LocalConstant.UserRole.USER, user.getRole())) {
            // user 不是 user
            return 2;
        }
        User admin = this.getById(adminUserId);
        if (admin == null) {
            // admin 不存在
            return  3;
        }
        if (!StringUtils.equals(LocalConstant.UserRole.ADMIN, admin.getRole())) {
            // admin 不是 admin
            return 4;
        }
        if (StringUtils.equals(user.getUserParentId(), adminUserId)) {
            // user 是 admin 的子账户
            return 5;
        }

        // 修改 关联关系
        user.setUserParentId(adminUserId);
        userMapper.updateByPrimaryKey(user);

        // 修改 UserDevice
        List<String> userPeerIds = userDeviceService.listUserCacheDeviceIds(userId);
        if (!CollectionUtils.isEmpty(userPeerIds)) {
            List<String> adminPeerIds = userDeviceService.listUserCacheDeviceIds(adminUserId);
            if (!CollectionUtils.isEmpty(adminPeerIds)) {
                userPeerIds.removeAll(adminPeerIds);
            }
        }

        String removePeerIds = null;
        if (!CollectionUtils.isEmpty(userPeerIds)) {
            removePeerIds = String.join(",", userPeerIds);
        }

        // 修改 Owner
        List<String> userOwnerPeerIds = userDeviceService.listOwnerPeerIds(userId);
        if (!CollectionUtils.isEmpty(userOwnerPeerIds)) {
            List<String> adminOwnerPeerIds = userDeviceService.listOwnerPeerIds(adminUserId);
            if (!CollectionUtils.isEmpty(adminOwnerPeerIds)) {
                userOwnerPeerIds.removeAll(adminOwnerPeerIds);
            }
        }

        String removeOwnerPeerIds = null;
        if (!CollectionUtils.isEmpty(userOwnerPeerIds)) {
            removeOwnerPeerIds = String.join(",", userOwnerPeerIds);
        }
        userDeviceService.correlateUserDevice(userId, null , removePeerIds,null, removeOwnerPeerIds, param.getLoginUserId());
        //删除与role之间的关系
        roleUserService.deleteByUserId(userId);

        //删除tvu_bookmark_share中的分享关系
        Long updateTime=System.currentTimeMillis();
        userMapper.updateShareByUser(userId,updateTime);
        return 0;
    }

    @Override
    public User getParentUser(String userId) {
        User user = this.getById(userId);
        if (user == null) {
            return null;
        }
        if (StringUtils.isEmpty(user.getUserParentId())) {
            return null;
        }
        return getById(user.getUserParentId());
    }

    @Override
    public int deleteUser(String userId) {
        int num = userMapper.deleteByPrimaryKey(userId);
        if (num == 0) {
            return 1;
        }
        return 0;

    }

    @Override
    public Result getSessionByEmail(String email) {
        Result<String> result = userGroupFeignService.getSessionByEmail(email);
        if (result.assertSuccess()) {
            return result;
        }
        return ResultUtil.error("81002401", "Get session failed", result);
    }

    @Override
    public PageInfo<UserIdWithEmail> pageAdminIdAndEmail(String email, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        email = MyUtil.formatCondition(email);
        List<UserIdWithEmail> list = userMapper.listAdminIdAndEmail(email);
        return new PageInfo<>(list);
    }

	@Override
	public LoginUser getLoginUserByUserId(String userId) throws Exception {
		return userMapper.getLoginUserByUserId(userId);
	}
    @Override
    public LoginUser getParentUserByUserId(String userId) throws Exception {
        return userMapper.getParentUserByUserId(userId);
    }

    /**
     *
     * 补充完整的 LoginUser 信息，包括 role,email,active,createUserId 等信息,
     * 并 Set 到 redis 中。
     *
     *
     * @param loginUser
     * @return full user info
     */
	private   User supplementAndSetLoginUser(LoginUser loginUser,String token){

	    if(loginUser == null){
	        return null;
        }

        User user = this.getByEmail(loginUser.getEmail());
        if (user != null) {
            // 将用户基本信息封装到LoginUser中去
            loginUser.setRole(user.getRole());
            loginUser.setActive(user.getActive());
            loginUser.setPhone(user.getPhone());
            loginUser.setCreateUserId(user.getCreateUserId());
            loginUser.setUserParentId(user.getUserParentId());

            try {
                if (StringUtils.isNotBlank(user.getUserParentId())){
                    Result<com.tvunetworks.center.common.model.User> userInfoById = userGroupFeignService.getUserInfoById(user.getUserParentId());
                    if (userInfoById!=null && userInfoById.assertSuccess()){
                        com.tvunetworks.center.common.model.User result = userInfoById.getResult();
                        if(result!=null){
                            loginUser.setParentName(result.getUserName());
                            if(result.getUserName()==null && result.getLastName()!=null && result.getFirstName()!=null){
                                loginUser.setParentName(result.getFirstName() + result.getLastName());
                            }
                        }
                    }
                }
            } catch (Exception e) {
               ResultUtil.exception("Failed to obtain the properties of the parent account");
            }


        } else {
            loginUser.setRole("4");
            loginUser.setActive("1");
            // 登陆用户数据库中不存在，添加到数据库中
            user = new User();
            user.setId(loginUser.getId());
            user.setEmail(loginUser.getEmail());
            user.setRole("4");
            user.setActive("1");
            user.setRegisterTime(String.valueOf(System.currentTimeMillis()));
            userMapper.insert(user);
        }
        redisUtil.set(LocalConstant.REDIS_LOGIN_USER_KEY + token, loginUser, sessionValidTime);
        return user;
    }

	@Override
	public Result<Object> getUserListByParentUserId(String parentUserId,String search,Integer currentPageNum,Integer everyPageNum) throws Exception {
	     PageHelper.startPage(currentPageNum, everyPageNum);
	     List<LoginUser> userListByParentUserIdList = userMapper.getUserListByParentUserId(parentUserId,search);
		 return ResultUtil.success(new PageInfo(userListByParentUserIdList));
	}

    @Override
    public void updateUserEmail(LoginUser loginUser, UpdateUserEmailParam param) {
	    // 检查用户权限
        String loginUserRole = loginUser.getRole();
        if (!(LocalConstant.UserRole.SUPER_ADMIN.equals(loginUserRole) || LocalConstant.UserRole.SUPPORT.equals(loginUserRole))) {
            ServerException.Exception(ResultUtil.noAuthority());
        }

        String userId = param.getUserId();
        String newEmail = param.getNewEmail();
        // 检查 CC userId 用户是否存在，检查新的 email 是否已存在
        User user = updateUserEmailCheckCC(userId, newEmail);

        if (StringUtils.equals(user.getEmail(), newEmail)) {
            return;
        }
        // 检查 UserService userId 用户是否存在，检查新的 email 是否已存在
        updateUserEmailCheckUserService(userId, newEmail);

        // TODO 检查新的 email 在 Dashboard 是否已存在

        // 调用 userservice 修改 email
        Result<String> userserviceUpdateResult = userGroupFeignService.updateUserEmail(param);
        if (!userserviceUpdateResult.assertSuccess()) {
            ServerException.Exception(ResultConstant.UpdateUserEmail.USERSERVICE_UPDATE_EMAIL_FAILED.setResult(userserviceUpdateResult));
        }

        // TODO 调用 Dashboard 修改 email

        user.setEmail(newEmail);
        userMapper.updateByPrimaryKey(user);
    }

    @Override
    public ExcelData exportUser(LoginUser loginUser, SearchUserParam param) {
	    param.setNotNeedCount(true);
        PageInfo<PageUserVo> userPageInfo = this.pageUser(loginUser, param, 1, 9999999);
        List<PageUserVo> list = userPageInfo.getList();
//        if (CollectionUtils.isEmpty(list)) {
//            throw new ServerException(ResultConstant.ExportUser.USER_NOT_EXIST_IN_CC);
//        }
        ExcelData excelData = new ExcelData();
        excelData.setName("User Report");
        String[] titles;
        if (LocalConstant.UserRole.ADMIN.equalsIgnoreCase(param.getAccountType())) {
            titles = new String[]{"email","firstName","lastName","accountType","role","status", "phone", "remark", "agreement"};
        } else {
            titles = new String[]{"email","firstName","lastName","accountType","role","status", "phone", "remark", "agreement", "adminEmail"};
        }
        excelData.setTitles(titles);
        List<ExportUserVo> exportList = new ArrayList<>();
        for (PageUserVo vo : list) {
            exportList.add(vo.convertToExportUserVo());
        }
        excelData.setContent(exportList);
        return excelData;
    }

    @Override
    @Transactional
    public Result deleteAccout(LoginUser loginUser,String userId) throws Exception{
	    //setActive
        setActive(userId,"0");
        //查询当前用户信息
        LoginUser loginUserByUserId = userMapper.getLoginUserByUserId(userId);
        //用户权限校验
        if("1".equals(loginUser.getRole())){
            return ResultUtil.exception("supper admin role can not delete accout");
        }
        if("3".equals(loginUser.getRole()) && !loginUserByUserId.getUserParentId().equals(loginUser.getId())){
            return ResultUtil.exception("admin role can only can delete your own child accounts ");
        }
        if("4".equals(loginUser.getRole())){
            return ResultUtil.exception("user role can only can not delete accout ");
        }
        //tvu_user_delete_record备份
        UserDeleteRecord user = new UserDeleteRecord();
        user.setId(loginUserByUserId.getId());
        user.setEmail(loginUserByUserId.getEmail());
        user.setPhone(loginUserByUserId.getPhone());
        user.setRole(loginUserByUserId.getRole());
        user.setCreateUserId(loginUserByUserId.getCreateUserId());
        user.setUserParentId(loginUserByUserId.getUserParentId());
        userdeleteRecordMapper.insert(user);
        userdeleteRecordMapper.deteteTokenCode(userId);
        userdeleteRecordMapper.deteteUserBookmark(userId);
        userdeleteRecordMapper.deteteUserDevice(userId);
        userdeleteRecordMapper.deteteUserFeature(userId);
        //删除tvu_bookmark_share中的数据
        Long updateTime=System.currentTimeMillis();
        userMapper.updateShareByUser(userId,updateTime);
        return ResultUtil.success();
    }

    @Override
    public void invalidateUser(LoginUser loginUser, String userId, boolean deleteSonAccountFlag) {
        User targetUser = userMapper.getById(userId);
        if (targetUser == null) {
            throw new ServerException(ResultConstant.DeleteUser.TARGET_USER_NOT_EXIST);
        }
        log.error("invalidateUser start loginUser:[{}] targetUser:[{}]", loginUser, targetUser);
        String loginUserRole = loginUser.getRole();
        String targetUserRole = targetUser.getRole();
        //用户权限校验
        if (LocalConstant.UserRole.SUPER_ADMIN.equalsIgnoreCase(loginUserRole)) {
            if (LocalConstant.UserRole.SUPER_ADMIN.equalsIgnoreCase(targetUserRole)) {
                throw new ServerException(ResultConstant.DeleteUser.SUPER_ADMIN_CAN_NOT_DELETE_SUPER_ADMIN);
            }
        } else if (LocalConstant.UserRole.SUPPORT.equalsIgnoreCase(loginUserRole)) {
            if (LocalConstant.UserRole.SUPER_ADMIN.equalsIgnoreCase(targetUserRole) || LocalConstant.UserRole.SUPPORT.equalsIgnoreCase(targetUserRole)) {
                throw new ServerException(ResultConstant.DeleteUser.SUPPORT_CAN_NOT_DELETE_SUPER_ADMIN_AND_SUPPORT);
            }
        } else if (LocalConstant.UserRole.ADMIN.equalsIgnoreCase(loginUserRole)) {
            if (LocalConstant.UserRole.SUPER_ADMIN.equalsIgnoreCase(targetUserRole) || LocalConstant.UserRole.SUPPORT.equalsIgnoreCase(targetUserRole) || LocalConstant.UserRole.ADMIN.equalsIgnoreCase(targetUserRole)) {
                throw new ServerException(ResultConstant.DeleteUser.ADMIN_CAN_NOT_DELETE_SUPER_ADMIN_AND_SUPPORT_AND_ADMIN);
            }
            if (!StringUtils.equals(loginUser.getId(), targetUser.getUserParentId())) {
                throw new ServerException(ResultConstant.DeleteUser.ADMIN_CAN_NOT_DELETE_NOT_BELONE_USER);
            }
        } else if (LocalConstant.UserRole.USER.equalsIgnoreCase(loginUserRole)) {
            throw new ServerException(ResultConstant.DeleteUser.USER_CAN_NOT_DELETE_OTHERS);
        }

        if (LocalConstant.UserRole.ADMIN.equalsIgnoreCase(targetUserRole)) {
            List<String> userIds = this.listSonUserIds(userId);
            if (!CollectionUtils.isEmpty(userIds)) {
                for (String id : userIds) {
                    User son = userMapper.getById(id);
                    this.invalidateUser(son, deleteSonAccountFlag);
                }
            }
            roleManagementService.deleteByUserId(userId);
        }

        invalidateUser(targetUser, true);
        log.error("invalidateUser end loginUser:[{}] targetUser:[{}]", loginUser, targetUser);
    }

    @Override
    public PageInfo<GetUserByRoleIdVo> pageSonUserByParentUserId(PageSonUserParam param) {
        PageHelper.startPage(param.getPageNum(), param.getPageSize());
        return new PageInfo<>(userMapper.pageSonUserByParentUserId(param));
    }

    private void invalidateUser(User user, boolean deleteSonAccountFlag) {

        if (user == null) {
            return;
        }
        log.error("invalidateUser user:[{}]", user);
        String userId = user.getId();
        UserThreadPool.SERVICETHREADPOOL.execute(() -> {
            tokenFeignService.invalidateUserAllToken(userId);
            userBookmarkService.deleteUserAllBookmark(userId);
            userDeviceService.removeUserAllDevice(userId);
            userFeatureService.removeUserAllFeature(userId);
            roleUserService.deleteByUserId(userId);
        });

        if (deleteSonAccountFlag) {
            // deactive
            this.setActive(userId, "0");

            user = userMapper.getById(userId);
            // 塞到 UserDeleteRecord
            userDeleteRecordService.addRecord(user);

            // 删除 user
            userMapper.deleteByPrimaryKey(userId);
        }else {
            user.setUserParentId(null);
            userMapper.updateByPrimaryKey(user);
        }

    }

    private User updateUserEmailCheckCC(String userId, String newEmail) {
        User exist = this.getById(userId);
        if (exist == null) {
            ServerException.Exception(ResultConstant.UpdateUserEmail.USER_NOT_EXIST_IN_CC);
        }

        User exailExist = this.getByEmail(newEmail);
        if (exailExist != null) {
            ServerException.Exception(ResultConstant.UpdateUserEmail.EMAIL_EXIST_IN_CC);
        }
        return exist;
    }

    private void updateUserEmailCheckUserService(String userId, String newEmail) {
        Result result = userGroupFeignService.getUserInfoById(userId);
        if (!result.assertSuccess()) {
            ServerException.Exception(ResultConstant.UpdateUserEmail.USER_NOT_EXIST_IN_USERSERVICE);
        }
        // 检查新的 email 在 userservice 是否已存在
        com.tvunetworks.center.common.model.User userserviceExist = userGroupFeignService.getUserserviceUserByEmail(newEmail);
        if (userserviceExist != null) {
            ServerException.Exception(ResultConstant.UpdateUserEmail.EMAIL_EXIST_IN_USERSERVICE);
        }
    }

    @Override
    public Result<List<UserInfoVo>> sonUserByParentUserEmail(String userParentEmail) {
        String parentId = userMapper.getByEmali(userParentEmail);
        if (StringUtils.isNotBlank(parentId)){
            List<UserInfoVo> userInfoVos = userMapper.pageSonUsersByParentUserId(parentId);
           return ResultUtil.success(userInfoVos);
        }
        return ResultUtil.success(new ArrayList<>()) ;
    }

    @Override
    public void createUserInCcService(String  userId,String email) {
        //1.check exist in cc service
        User user = this.getById(userId);
        if (user != null) {
            log.error("createUserInCcService>>>>>user exist in cc service,userId:[{}],user:[{}]", userId, user);
            return;
        }
        //2.check exist in userGroup Service
        Result<com.tvunetworks.center.common.model.User> userResult = userGroupFeignService.getUserInfoById(userId);
        if (!userResult.assertSuccess() || userResult.getResult() == null) {
            log.error("createUserInCcService>>>>>>>>>get UserMessage from userGroup Service failed. userId:[{}], userResult:[{}]", userId, userResult);
            throw new ServerException(ResultConstant.User.USER_NOT_EXIST);
        }
        //create user in cc service ,role is user
        LoginUser loginUser = new LoginUser()
                .setId(userId)
                .setEmail(email);
        this.createUser(loginUser);
    }

    @Override
    public List<String> listSonUserIdByParentId(String userId) {
        return userMapper.listSonUserIds(userId);
    }

    @Override
    public List<User> getUserOfAdminAndHaveSonUser() {
        return userMapper.getUserOfAdminAndHaveSonUser();
    }
}
